﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Security.Cryptography;

namespace ShadowinServer
{
    public class RSAPublicKEY
    {
        private BigInteger modulus;
        private BigInteger exponent;

        public RSAPublicKEY(BigInteger n,BigInteger e)
        {
            this.modulus = n;
            this.exponent = e;
        }

        public BigInteger Modulus
        {
            get { return modulus; }
        }
        public BigInteger Exponent
        {
            get { return exponent; }
        }

    }

    public class RSAPrivateKEY
    {
        private BigInteger d;
        private BigInteger modulus;

        public RSAPrivateKEY(BigInteger d,BigInteger n)
        {
            this.d = d;
            this.modulus = n;
        }
        public BigInteger D
        {
            get { return d; }
        }
        public BigInteger Modulus
        {
            get { return modulus; }
        }

    }

    public class RSAKEY
    {
        private BigInteger d;
        private BigInteger modulus;
        private BigInteger exponent;

        public RSAKEY(BigInteger d,BigInteger n,BigInteger e)
        {
            this.d = d;
            this.modulus = n;
            this.exponent = e;
        }
        public BigInteger D
        {
            get { return d; }
        }
        public BigInteger Modulus
        {
            get { return modulus; }
        }
        


    }

    public class RSA
    {
        public RSA()
        {
            //KEY = new RSAKEY();
            //KEY.Modulus = new BigInteger("128463516502120742073491611151586955140034099102773553284548256947910709586367239826630762979961408895469104774498413529089968892796737823386877175286343256321306880861931691755864420237424386831534501803478894423579578268112674434668402166429969219986111602595387204630478508452698172936912654376616701897427", 10);
            //KEY.Exponent = new BigInteger("65537", 10);
            //KEY.D = new BigInteger("93288305497183733719297690738458067488968107244750277673958537080808802518186515675557490757012426143295628948959038355073466889634593382221161458813001009597182091643276580848268466758360143416855784425841764179128266761205622240475417530161517293960147417942584834503928556910190890734602780191685905877953", 10);
        }

        /**/
        /* 
         * 功能：用于生成Key
        */

        public static RSAKEY GenKey()
        {
            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
            RSAParameters keys = rsa.ExportParameters(true);

            BigInteger bign = new BigInteger(keys.Modulus);
            BigInteger bige = new BigInteger(keys.Exponent);
            BigInteger bigd = new BigInteger(keys.D);

            return new RSAKEY(bigd, bign, bige);
        }

        /**/
        /* 
         * 功能：用指定的公钥(n,d)加密指定字符串source 
        */
        public static string Encrypt(string source, BigInteger D, BigInteger Modulus)
        {
            int len = source.Length;
            int len1 = 0;
            int blockLen = 0;
            if ((len % 128) == 0)
                len1 = len / 128;
            else
                len1 = len / 128 + 1;
            string block = "";
            string temp = "";
            for (int i = 0; i < len1; i++)
            {
                if (len >= 128)
                    blockLen = 128;
                else
                    blockLen = len;
                block = source.Substring(i * 128, blockLen);
                byte[] oText = System.Text.Encoding.Default.GetBytes(block);
                BigInteger biText = new BigInteger(oText);
                BigInteger biEnText = biText.modPow(D,Modulus);
                string temp1 = biEnText.ToHexString();
                temp += temp1;
                len -= blockLen;
            }
            return temp;
        }

        public static string Encrypt(string source, RSAPrivateKEY priKey)
        {
            return Encrypt(source,priKey.D,priKey.Modulus);
        }

        /**/
        /* 
         * 功能：用指定的公钥(n,e)解密指定字符串source 
        */

        public static string Decrypt(string source, BigInteger Exponent, BigInteger Modulus)
        {
            int len = source.Length;
            int len1 = 0;
            int blockLen = 0;
            if ((len % 256) == 0)
                len1 = len / 256;
            else
                len1 = len / 256 + 1;
            string block = "";
            string temp = "";
            for (int i = 0; i < len1; i++)
            {
                if (len >= 256)
                    blockLen = 256;
                else
                    blockLen = len;
                block = source.Substring(i * 256, blockLen);
                BigInteger biText = new BigInteger(block, 16);
                BigInteger biEnText = biText.modPow( Exponent, Modulus);
                string temp1 = System.Text.Encoding.Default.GetString(biEnText.getBytes());
                temp += temp1;
                len -= blockLen;
            }
            return temp;
        }

        public static string Decrypt(string source, RSAPublicKEY pubKey)
        {
            return Decrypt(source, pubKey.Exponent, pubKey.Modulus);
        }
    }
}
